{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "6c43a333",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Go deeper into the NumPy library for array computing.\n",
    "# This will include more internal detail about the ndarray type and more advanced array mapnipulation\n",
    "# and algorithms. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ced2cdc8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ndarray Object Internals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "725f6786",
   "metadata": {},
   "outputs": [],
   "source": [
    "# The NumPy ndarray provides a way to interpret a block of 同类型 data(连续或离散) as a multidimensional array\n",
    "# object. The data type or dtype, determines how the data is interpreted as being floating point, integer,\n",
    "# boolean, or any of the other types we've been looking at."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "23d4493f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Part of what makes ndarray flexible is that every array object is a strided view (带步长的视图) \n",
    "# on a block of data.\n",
    "#### stride（步长）指的是在内存中从一个元素移动到下一个元素所需跨越的字节数，每个ndarray 都有一个属性 arr.strides\n",
    "#### 它告诉你，对于每个维度，当索引增加1时，需要在内存中“跳过多少字节”才能到下一个元素。\n",
    "#### a strided view = 通过不同的步长定义出的对同一块数据的不同视角\n",
    "#### NumPy中的数组可以共享同一块底层数据，只是用不同的shape和stride来解释那块内存"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8a038bce",
   "metadata": {},
   "outputs": [],
   "source": [
    "# For example, how the array view arr[::2,::-1] does not copy any data. The reason is that the ndarray is more\n",
    "# than just a chunk of memory and a dtype; it also has \"striding\" information that enables the array to move\n",
    "# through memory with varying step size. the ndarray internally consis of the following:\n",
    "    # A pointer to data -- that is, a block of data in RAM or in a memory-mapped file.\n",
    "    # the data type or dtype,describing fixed-size value cells in the array\n",
    "    # A tuple indicating the array's shape\n",
    "    # A tuple of strides, integers indicating the number of bytes to \"step\" in order to advance one element\n",
    "        # along a dimension."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "35bb1038",
   "metadata": {},
   "outputs": [],
   "source": [
    "# a simple mockup(简化的展示或prototype) of the ndarray innards(内部机制或内部数据结构)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "921da03a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10, 5)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# For example a 10 x 5 array would have shape (10, 5)\n",
    "import numpy as np\n",
    "np.ones((10,5)).shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a4889c59",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A typical(C order) 3 x 4 x 5 array of float64(8-byte) values has strides (160, 40, 8)\n",
    "ints = np.ones(10,dtype=np.uint16)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "5c60194f",
   "metadata": {},
   "outputs": [],
   "source": [
    "floats = np.ones(10,dtype=np.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6b85c837",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.issubdtype(ints.dtype,np.integer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "1fe88263",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.issubdtype(floats.dtype,np.floating)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "fb04959e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Advanced Array Manipulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "9c197afc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# There are many ways to work with arrays beyond fancy indexing, slicing, and boolean subsetting（indexing）.\n",
    "# while much of heavy lifting for data analysis applications is handled by higher-level functions in pandas,\n",
    "# you may at some point to write a data algorithm that is not found in one of the existing libraries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "bda339a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Reshaping Array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "4ce211e3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# In many cases, you can convert an array from one shape to another without copying any data. To do this, pass\n",
    "# a tuple indicating the new shape to the reshape array instance method. For example, suppose we had a one-\n",
    "# dimensional array of values that we wished to rearrange into a matrix:\n",
    "arr = np.arange(8)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "2d30a89c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5],\n",
       "       [6, 7]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.reshape((4,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "6f25a301",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3],\n",
       "       [4, 5, 6, 7]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A multidimensional array can also be resahped\n",
    "arr.reshape((4,2)).reshape((2,4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "284b137b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# One of the passed shape dimensions can be -1, in which case the value used for that dimension will be \n",
    "# inferred (被推测出) from the data.\n",
    "arr = np.arange(15)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "02436593",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2],\n",
       "       [ 3,  4,  5],\n",
       "       [ 6,  7,  8],\n",
       "       [ 9, 10, 11],\n",
       "       [12, 13, 14]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.reshape((5,-1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "59b97359",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Since an array's shape attribute is a tuple, it can be passed to reshape,too\n",
    "other_arr = np.ones((3,5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "f80268fc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 5)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "other_arr.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "66e1ba30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.reshape(other_arr.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "2e1ff28a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2],\n",
       "       [ 3,  4,  5],\n",
       "       [ 6,  7,  8],\n",
       "       [ 9, 10, 11],\n",
       "       [12, 13, 14]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The opposite operation of reshape from one-dimensional to a higer dimension is typically known as \n",
    "# flattening or raveling.\n",
    "arr = np.arange(15).reshape((5,3))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "bd6e7dfe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.ravel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "23aebd33",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# ravel does not produce a copy of the underlying values if the values in the result were contiguous in the \n",
    "# original array. The flatten method behaves like ravel except it returns a copy of the data.\n",
    "arr.flatten()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "616d4969",
   "metadata": {},
   "outputs": [],
   "source": [
    "# The data can be reshaped or raveled in different orders. This is 一个微妙的话题 ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "f65481c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# C Versus Fortran order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "d8a2974f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# NumPy is able to adapt to many different layous of your data in memory. By default, NumPy arrays area created\n",
    "# in row major order. Spatially this means that if you have a two-dimensional array of data, the items in each\n",
    "# row of the array are stored in 临近的 memory locations. The alternative to row major ordering is column major\n",
    "# order, which means that values within each column of data are stored in 临近的 memory locations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "22208f49",
   "metadata": {},
   "outputs": [],
   "source": [
    "# For historical reasons, row and column major order are also know as C and Fortran order, respectively.\n",
    "# Functions like reshape and ravel accept an order argument indicating the order to use the data in the array.\n",
    "# This is usually set to 'C' or 'F' in most cases"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "0b97f2c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Concatenating and Splitting Arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "0a73b2c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# numpy.concatenate takes a sequence(tuple,list,etc.) of arrays and joins them together in order along the input\n",
    "# axis\n",
    "arr1 = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "arr2 = np.array([[7, 8, 9], [10, 11, 12]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "e92f41cf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "1d20da74",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7,  8,  9],\n",
       "       [10, 11, 12]])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "077182aa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3],\n",
       "       [ 4,  5,  6],\n",
       "       [ 7,  8,  9],\n",
       "       [10, 11, 12]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# concatenate down the row\n",
    "np.concatenate([arr1,arr2],axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "c3dc8032",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3,  7,  8,  9],\n",
       "       [ 4,  5,  6, 10, 11, 12]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# concatenate across the column\n",
    "np.concatenate([arr1,arr2],axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "8659778d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3],\n",
       "       [ 4,  5,  6],\n",
       "       [ 7,  8,  9],\n",
       "       [10, 11, 12]])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# There are some convenience functions, like vstack and hstack, for common kind of concatenation.\n",
    "# The preceding operations could have been expressed as\n",
    "\n",
    "# stack arrays in sequence vertially(row wise)\n",
    "np.vstack((arr1,arr2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "75ffe3c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3,  7,  8,  9],\n",
       "       [ 4,  5,  6, 10, 11, 12]])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# stack arrays in sequence horizontally(column wise)\n",
    "np.hstack((arr1,arr2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "d9b6295c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.12937299, -0.84013549],\n",
       "       [-0.67174167, -0.23149486],\n",
       "       [-0.10569142, -0.01111608],\n",
       "       [-0.85891675,  0.5073848 ],\n",
       "       [ 1.03764307, -0.09365541]])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# split, one the other hand,slices apart an array into multiple arrays along an axis\n",
    "arr = np.random.randn(5,2)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "be8ea79a",
   "metadata": {},
   "outputs": [],
   "source": [
    "first,sencod,third = np.split(arr, [1,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "184a3074",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.12937299, -0.84013549]])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "c6b9cc8a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.67174167, -0.23149486],\n",
       "       [-0.10569142, -0.01111608]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sencod"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "39dfd95a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.85891675,  0.5073848 ],\n",
       "       [ 1.03764307, -0.09365541]])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "third"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "8d26ac01",
   "metadata": {},
   "outputs": [],
   "source": [
    "# The value [1,3] passed to np.split indicate the indices at which to split the array into pieces."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "a22cb556",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Stacking helpers: r_ and c_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "d0aaccda",
   "metadata": {},
   "outputs": [],
   "source": [
    "# There are two special objects in the NumPy namespace, r_ and c_, that make stacking arrays more concise\n",
    "arr = np.arange(6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "b3062a53",
   "metadata": {},
   "outputs": [],
   "source": [
    "arr1 = arr.reshape((3,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "cda66019",
   "metadata": {},
   "outputs": [],
   "source": [
    "arr2 = np.random.randn(3,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "fc6579be",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5]])"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "9eea88ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.59343662, -0.52964801],\n",
       "       [-1.90135012,  0.263411  ],\n",
       "       [-2.11600392,  1.53110914]])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "9970241c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.        ,  1.        ],\n",
       "       [ 2.        ,  3.        ],\n",
       "       [ 4.        ,  5.        ],\n",
       "       [-0.59343662, -0.52964801],\n",
       "       [-1.90135012,  0.263411  ],\n",
       "       [-2.11600392,  1.53110914]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# r_ 是简写形式，row-wise concatenate arrays\n",
    "np.r_[arr1,arr2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "bb66d6e3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.        ,  1.        ,  0.        ],\n",
       "       [ 2.        ,  3.        ,  1.        ],\n",
       "       [ 4.        ,  5.        ,  2.        ],\n",
       "       [-0.59343662, -0.52964801,  3.        ],\n",
       "       [-1.90135012,  0.263411  ,  4.        ],\n",
       "       [-2.11600392,  1.53110914,  5.        ]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.c_[np.r_[arr1,arr2],arr]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "a4184d12",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  1, -10],\n",
       "       [  2,  -9],\n",
       "       [  3,  -8],\n",
       "       [  4,  -7],\n",
       "       [  5,  -6]])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# These additionally can translate slices to arrays\n",
    "np.c_[1:6,-10:-5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "13790f24",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Repeating Elements: tile and repeat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "1d4683ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Two useful tools for repeating or replicating(重复或复制) arrays to produce larger arrays are the repeat and \n",
    "# tile functions. repeat replicates each element in an array some number of times, producing a larger array."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "13f294d0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(3)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "fa623932",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 0, 0, 1, 1, 1, 2, 2, 2])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.repeat(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "6e234f7a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 0, 1, 1, 1, 2, 2, 2, 2])"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# By default, if you pass an integer, each element will be repeated that number of times. If you pass an array of\n",
    "# integers, each element can be repeated a different number of times\n",
    "arr.repeat([2,3,4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "274a0e9d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Multidimensional arrays can have their elements repeated along a particular axis\n",
    "arr = np.random.randn(2,2)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "d688f109",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456],\n",
       "       [ 0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622],\n",
       "       [ 0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.repeat(2,axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "0e799683",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.49924921,  0.49924921, -0.51397456, -0.51397456,  0.79401525,\n",
       "        0.79401525, -1.26572622, -1.26572622])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Note that if no axis is passed, the array will be flattened first, which is likely not what you want.\n",
    "arr.repeat(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "2993b807",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456],\n",
       "       [ 0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622],\n",
       "       [ 0.79401525, -1.26572622],\n",
       "       [ 0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Similarly, you can pass an array of integers \n",
    "# when repeating a multidimensional array to repeat a given slice (这里slice = 每一行)\n",
    "# a different number of times\n",
    "arr.repeat([2,3], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "a80ce2db",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921,  0.49924921, -0.51397456, -0.51397456, -0.51397456],\n",
       "       [ 0.79401525,  0.79401525, -1.26572622, -1.26572622, -1.26572622]])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.repeat([2,3],axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "277d31c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# tile, on the other hand, is a shortcut for stacking copies of an array along an axis.\n",
    "# Visually you can think of it as 类似于 \"铺瓷砖\"\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "dfdde33c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456,  0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622,  0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.tile(arr,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "bfa899bb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# the second argument is the number of tiles; with a scalar, the tiling is made row by row.\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "cd53663d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.49924921, -0.51397456,  0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622,  0.79401525, -1.26572622],\n",
       "       [ 0.49924921, -0.51397456,  0.49924921, -0.51397456],\n",
       "       [ 0.79401525, -1.26572622,  0.79401525, -1.26572622]])"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# the second argument to tile can be a tuple indicating the layout of \"tiling\".(\"平铺\"的布局方式，即各维度上的\n",
    "# 平铺次数)-- 也就是这个tuple 决定了平铺的布局结构(layout).\n",
    "# tuple（2,2）\n",
    "    # 第一个值决定：沿行方向复制2次\n",
    "    # 第二个值决定：沿列方向复制2次\n",
    "np.tile(arr, (2,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "c8908f1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Fancy Indexing Equivalents: take and put"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "29aa2118",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0, 100, 200, 300, 400, 500, 600, 700, 800, 900])"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# one way to get and set subsets of arrays is by fancy indexing using integer arrays\n",
    "arr = np.arange(10) * 100\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "d3e33840",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([700, 100, 200, 600])"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inds = [7,1,2,6]\n",
    "arr[inds]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "6962bf6f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([700, 100, 200, 600])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# There are alternative ndarray methods that are useful in the special case of only making a selection on single\n",
    "# axis\n",
    "arr.take(inds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "23e16536",
   "metadata": {},
   "outputs": [],
   "source": [
    "arr.put(inds, 42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "ad40484b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0,  42,  42, 300, 400, 500,  42,  42, 800, 900])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "7063a786",
   "metadata": {},
   "outputs": [],
   "source": [
    "arr.put(inds, [40,41,42,43])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "67043d96",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0,  41,  42, 300, 400, 500,  43,  40, 800, 900])"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "d93abfcf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# to use take along other axes, you can pass the axis keyword.\n",
    "inds = [2,0,2,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "0d3c27c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "arr = np.random.randn(2,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "516db908",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.26412922,  0.29390158, -0.74192162, -1.07743675],\n",
       "       [-1.21450464,  0.21618883, -0.33694911, -0.76623648]])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "5a032c46",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.74192162, -1.26412922, -0.74192162,  0.29390158],\n",
       "       [-0.33694911, -1.21450464, -0.33694911,  0.21618883]])"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.take(inds, axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "fc84cdcd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.26412922,  0.29390158, -0.74192162, -1.07743675],\n",
       "       [-1.21450464,  0.21618883, -0.33694911, -0.76623648],\n",
       "       [-1.26412922,  0.29390158, -0.74192162, -1.07743675],\n",
       "       [-1.21450464,  0.21618883, -0.33694911, -0.76623648]])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.take([0,1,0,1],axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "54040351",
   "metadata": {},
   "outputs": [],
   "source": [
    "# put does not accept an axis argument but rather indexes into the flattened(one-dimensional, C order) version\n",
    "# of array. Thus when you need to set elements using an index on other axes, it is best to use []-based indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "f1228190",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Broadcasting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "39d359eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4])"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Broadcasting governs how operations work between arrays of different shapes.\n",
    "# It can be a powerful feature, but one that can cause confusion,even for experienced user.\n",
    "# The simplest example of broadcasting occurs when combining a scalar value with an array.\n",
    "arr = np.arange(5)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "84d21879",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  4,  8, 12, 16])"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr * 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "e2cd2b18",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Here we say that the scalar value 4 has been broadcast to all of the other elements \n",
    "# in the multiplication operation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "8cff7e3e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.86003234,  1.10835552, -0.38458547],\n",
       "       [ 0.77429943, -2.47658685, -0.44769987],\n",
       "       [-0.27739658,  0.52904695,  0.76107479],\n",
       "       [ 2.06662832, -3.28308266, -1.56638121]])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# For example, we can demean(去均值化) each column of an array by subtracting the column means. \n",
    "# In this case, it is necessary only to subtract an array containing th emean of each column.\n",
    "arr = np.random.randn(4,3)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "2a87fcbb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.42587471, -1.03056676, -0.40939794])"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.mean(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "bfb97ad5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.28590705,  2.13892228,  0.02481247],\n",
       "       [ 0.34842472, -1.44602009, -0.03830193],\n",
       "       [-0.70327129,  1.55961371,  1.17047273],\n",
       "       [ 1.64075362, -2.2525159 , -1.15698327]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# demeaning the rows as a broadcast operation requires a bit more care. Fortunately, broadcasting potentially\n",
    "# lower dimensional values across any dimension of an array(like subtracting the row mean from each column of\n",
    "# a tow-dimensional array) is possible as long as you follow the rules.\n",
    "demeaned = arr - arr.mean(0)\n",
    "demeaned"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "64697026",
   "metadata": {},
   "outputs": [],
   "source": [
    "# THE BROADCASTING RULE\n",
    "# Two arrays are compatible for broadcasting if for each trailing dimension (i.e., starting from the end) the\n",
    "# lengths match or if either of the lenghts is 1. Broadcasting is then performed over the missing or length 1\n",
    "# dimensions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18fe2dc7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
